925D - Aztec Catacombs - CodeForces Solution


constructive algorithms *2600

Please click on ads to support us..

C++ Code:

/*
 * {...}
 */
#ifndef LOCAL
#define NDEBUG 1
#endif
#include<bits/stdc++.h>

int main(){
	std::ios::sync_with_stdio(0);std::cin.tie(0);
	int nnode,nedge;std::cin>>nnode>>nedge;
	std::vector<std::vector<int>> ad(nnode);
	for(int z=nedge,u,v;z--;){
		std::cin>>u>>v;
		--u;--v;
		//if(std::minmax(u,v)==std::pair{0,nnode-1}){
		//	std::cout<<"1\n1 "<<nnode<<'\n';
		//	return 0;
		//}
		ad[u].push_back(v);
		ad[v].push_back(u);
	}

	std::vector<int> dist(nnode,INT_MAX);
	std::queue<int> q;
	dist[0]=0;q.push(0);
	while(not q.empty()){
		int node=q.front();q.pop();
		auto const nextdist=dist[node]+1;
		if(nextdist<=3){
			for(int y:ad[node])if(dist[y]==INT_MAX){
				dist[y]=nextdist;
				q.push(y);
			}
		}
	}

	if(dist[nnode-1]<=3){
		// if there is an simple path, there must be a non simple path (length ==4, handled below),
		// or a simple path with length <=3.

		std::cout<<dist[nnode-1]<<'\n';

		std::vector<int> path;
		path.reserve(dist[nnode-1]+1);
		path.push_back(nnode-1);
		while(path.back()!=0)
			path.push_back(
					*std::find_if(
						begin(ad[path.back()]),end(ad[path.back()]),
						[&,nextdist=dist[path.back()]-1](int node){ return dist[node]==nextdist; }
						));
		assert(path.size()==(unsigned)dist[nnode-1]+1);

		std::for_each(path.rbegin(),path.rend(),[](int x){ std::cout<<x+1<<' '; });
		std::cout<<'\n';
		return 0;
	}

	// else: no simple path. min non simple path (1->nnode) len = 4

	auto iter=std::find(begin(dist),end(dist),2);
	if(iter!=end(dist)){
		auto const n2=int(iter-begin(dist));
		assert(dist[n2]==2);

		auto const n1=*std::find_if(
			begin(ad[n2]),end(ad[n2]),
			[&](int node){ return dist[node]==1; }
			);

		std::cout<<"4\n1 "<<n1+1<<' '<<n2+1<<" 1 "<<nnode<<'\n';
		return 0;
	}

	// else: no path len <= 4
	


	std::vector<char> vis(nnode);
	for(int c:ad[0]){
#ifdef LOCAL
		std::sort(begin(ad[c]),end(ad[c]));
#endif
		ad[c].erase(
				std::find(begin(ad[c]),end(ad[c]),0));
	}

	std::sort(begin(ad[0]),end(ad[0]),[&](auto a,auto b){ return ad[a].size()<ad[b].size(); });

	dist.assign(nnode,INT_MAX);

	for(int c:ad[0])if(not vis[c]){
		std::queue<int> q;
		assert(std::all_of(begin(dist),end(dist),[](auto x){ return x==INT_MAX; }));
		dist[c]=0;q.push(c);
		while(not q.empty()){
			int node=q.front();q.pop();
			auto const nextdist=dist[node]+1;
			for(int y:ad[node])if(dist[y]==INT_MAX){
				assert(y!=0);
				dist[y]=nextdist;
				if(nextdist==2){
					// found 0 -> c -> node -> y -(x)> c -(x)> nnode-1
					assert(not std::binary_search(begin(ad[c]),end(ad[c]),nnode-1));
					std::cout<<"5\n1 "<<c+1<<' '<<node+1<<' '<<y+1<<' '<<c+1<<' '<<nnode<<'\n';
					return 0;
				}
				q.push(y);
			}
		}

		// this is a clique. Mark as visited.
		for(int a:ad[c]){
			assert(not vis[a]);
			vis[a]=true;
			dist[a]=INT_MAX;
		}
		vis[c]=true;
		dist[c]=INT_MAX;
	}

#ifdef LOCAL
	for(int b:ad[0])
	for(int c:ad[b]){
		assert(c!=0);
		for(int d:ad[c]) if(d!=b)
			assert(std::binary_search(begin(ad[d]),end(ad[d]),b));
	}
#endif

	std::cout<<"-1\n";
}


Comments

Submit
0 Comments
More Questions

1051. Height Checker
695. Max Area of Island
402. Remove K Digits
97. Interleaving String
543. Diameter of Binary Tree
124. Binary Tree Maximum Path Sum
1465. Maximum Area of a Piece of Cake After Horizontal and Vertical Cuts
501A - Contest
160A- Twins
752. Open the Lock
1535A - Fair Playoff
1538F - Interesting Function
1920. Build Array from Permutation
494. Target Sum
797. All Paths From Source to Target
1547B - Alphabetical Strings
1550A - Find The Array
118B - Present from Lena
27A - Next Test
785. Is Graph Bipartite
90. Subsets II
1560A - Dislike of Threes
36. Valid Sudoku
557. Reverse Words in a String III
566. Reshape the Matrix
167. Two Sum II - Input array is sorted
387. First Unique Character in a String
383. Ransom Note
242. Valid Anagram
141. Linked List Cycle